#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 1024

typedef struct Line
{
    char content[MAX_LINE_LENGTH];
    int isSection;
    int isKeyValue;
    char section[MAX_LINE_LENGTH];
    char key[MAX_LINE_LENGTH];
    char value[MAX_LINE_LENGTH];
} Line;

Line *readIniFile(const char *filename, int *lineCount)
{
    FILE *file = fopen(filename, "r");
    if (!file)
    {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    Line *lines = NULL;
    char line[MAX_LINE_LENGTH];
    char currentSection[MAX_LINE_LENGTH] = "";
    *lineCount = 0;

    while (fgets(line, sizeof(line), file))
    {
        lines = realloc(lines, (*lineCount + 1) * sizeof(Line));
        Line *l = &lines[*lineCount];
        strcpy(l->content, line);
        l->isSection = 0;
        l->isKeyValue = 0;

        if (line[0] == '\n' || line[0] == ';' || line[0] == '#')
        {
            // 空行或注释行
        } else if (line[0] == '[' && line[strlen(line) - 2] == ']')
        {
            // 节
            l->isSection = 1;
            strncpy(currentSection, line + 1, strlen(line) - 3);
            currentSection[strlen(line) - 3] = '\0';
            strcpy(l->section, currentSection);
        } else
        {
            // 键值对
            char *pos = strchr(line, '=');
            if (pos)
            {
                l->isKeyValue = 1;
                strcpy(l->section, currentSection);
                strncpy(l->key, line, pos - line);
                l->key[pos - line] = '\0';
                strcpy(l->value, pos + 1);
                // 去掉换行符
                l->value[strcspn(l->value, "\n")] = '\0';
            }
        }

        (*lineCount)++;
    }

    fclose(file);
    return lines;
}

void setKeyValue(Line **lines, int *lineCount, const char *section, const char *key, const char *value)
{
    int sectionFound = 0;
    for (int i = 0; i < *lineCount; i++)
    {
        if ((*lines)[i].isSection && strcmp((*lines)[i].section, section) == 0)
        {
            sectionFound = 1;
        } else if (sectionFound && (*lines)[i].isKeyValue && strcmp((*lines)[i].key, key) == 0)
        {
            strcpy((*lines)[i].value, value);
            snprintf((*lines)[i].content, MAX_LINE_LENGTH, "%s=%s\n", key, value);
            return;
        }
    }

    // 如果节或键不存在，添加新的键值对
    if (sectionFound)
    {
        *lines = realloc(*lines, (*lineCount + 1) * sizeof(Line));
        snprintf((*lines)[*lineCount].content, MAX_LINE_LENGTH, "%s=%s\n", key, value);
        (*lines)[*lineCount].isSection = 0;
        (*lines)[*lineCount].isKeyValue = 1;
        strcpy((*lines)[*lineCount].section, section);
        strcpy((*lines)[*lineCount].key, key);
        strcpy((*lines)[*lineCount].value, value);
        (*lineCount)++;
    } else
    {
        *lines = realloc(*lines, (*lineCount + 3) * sizeof(Line));

        // 添加一个空行
        snprintf((*lines)[*lineCount].content, MAX_LINE_LENGTH, "\n");
        (*lines)[*lineCount].isSection = 0;
        (*lines)[*lineCount].isKeyValue = 0;

        snprintf((*lines)[*lineCount + 1].content, MAX_LINE_LENGTH, "[%s]\n", section);
        (*lines)[*lineCount + 1].isSection = 1;
        (*lines)[*lineCount + 1].isKeyValue = 0;
        strcpy((*lines)[*lineCount + 1].section, section);

        snprintf((*lines)[*lineCount + 2].content, MAX_LINE_LENGTH, "%s=%s\n", key, value);
        (*lines)[*lineCount + 2].isSection = 0;
        (*lines)[*lineCount + 2].isKeyValue = 1;
        strcpy((*lines)[*lineCount + 2].section, section);
        strcpy((*lines)[*lineCount + 2].key, key);
        strcpy((*lines)[*lineCount + 2].value, value);
        (*lineCount) += 3;
    }
}

void writeIniFile(const char *filename, Line *lines, int lineCount)
{
    FILE *file = fopen(filename, "w");
    if (!file)
    {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < lineCount; i++)
    {
        fputs(lines[i].content, file);
    }

    fclose(file);
}

int main()
{
    const char *filename = "../sysconfig.ini";
    int lineCount;
    Line *lines = readIniFile(filename, &lineCount);

    setKeyValue(&lines, &lineCount, "Settings", "Volume", "75");

    writeIniFile("../sysconfig3.ini", lines, lineCount);

    free(lines);
    return 0;
}
